package com.alan.service.impl;

import com.alan.common.RegisterConst;
import com.alan.entity.Account;
import com.alan.entity.RestBean;
import com.alan.entity.dto.RegisterUserDto;
import com.alan.mapper.UserMapper;
import com.alan.service.AuthenticationService;
import com.alan.util.BeanCopyUtils;
import com.alan.util.RedisCache;
import com.alan.util.ValidateCodeUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class AuthenticationServiceImplImpl implements AuthenticationService {

    @Resource
    private UserMapper mapper;

    @Resource
    private JavaMailSender sender;

    @Value("${spring.mail.username}")
    private String from;

    @Resource
    private RedisCache redisCache;


    //不知道怎么解决
    private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (username == null){
            throw new UsernameNotFoundException("用户名不能为空");
        }
        Account user = mapper.findAccountByUsernameOrEmail(username);
        if (user == null){
            throw new UsernameNotFoundException("用户名或密码错误");
        }

        return User
                .withUsername(user.getUsername())
                .password(user.getPassword())
                .roles("user")
                .build();

    }

    /**
     * 邮箱注册业务逻辑：
     * 1.先生成对应的验证码
     * 2.将邮箱和对应的验证码存在redis中（三分钟）
     * 3.发送验证码到指定的邮箱
     * 4.如果发送失败，从redis从删除
     * 5.用户在注册时，从redis中取出数据进行比对
     */
    @Override
    public RestBean sendValidateEmail(String email, String sessionId,boolean hasAccount) {

        String key = "email"+sessionId+":"+email+":"+hasAccount;
        if (!Objects.isNull(redisCache.getCacheObject(key))){
            Long expire = redisCache.redisTemplate.getExpire(key,TimeUnit.SECONDS);
            if (expire.longValue() >120){
                return RestBean.failure(RegisterConst.REQUEST_TOO_FREQUENTLY);
            }
        }

        if (!hasAccount && !Objects.isNull(mapper.findAccountByUsernameOrEmail(email)))
            return RestBean.failure(RegisterConst.ACCOUNT_EXISTED);
        else if (hasAccount && Objects.isNull(mapper.findAccountByUsernameOrEmail(email)))
            return RestBean.failure(RegisterConst.ACCOUNT_NOT_EXISTED);

        Integer code = ValidateCodeUtils.generateValidateCode(4);
        //发送简单邮件，简单邮件不包括附件等别的
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(email);
        message.setSubject("您的验证邮件");
        message.setText("验证码（3min有效）："+code);
        //发送邮件
        try {
            sender.send(message);
            String value = code.toString();
            redisCache.setCacheObject(key,value,3, TimeUnit.MINUTES);
            return RestBean.success(RegisterConst.SEND_SUCCESS);
        }catch (MailException e){
            e.printStackTrace();
            return RestBean.failure(RegisterConst.SEND_FAILURE);
        }

    }

    /*验证并注册*/
    @Override
    public RestBean<String> vaildateAndRegister(RegisterUserDto registerUserDto, String sessionId) {

        String key = "email"+sessionId+":"+registerUserDto.getEmail()+":false";
        if (!Objects.isNull(redisCache.getCacheObject(key))){
            String s = (String) redisCache.getCacheObject(key);
            if (null == s){
                return RestBean.failure("验证码失效，请重新发送");
            }
            if (s.equals(registerUserDto.getCode())){
                //成功,开始注册
//               MP可以
//                Account account = BeanCopyUtils.copyBean(registerUserDto, Account.class);
                if (mapper.createAccount(registerUserDto.getUsername(),
                        registerUserDto.getEmail(),
                        encoder.encode(registerUserDto.getPassword()))>0) {
                    redisCache.deleteObject(key);
                    return RestBean.success("注册成功");
                }else return RestBean.failure("系统错误！请联系管理员");
            }else return RestBean.failure("验证码错误，请检查");
        }else {
            return RestBean.failure("请先获取验证码");
        }

    }

    @Override
    public RestBean<String> validateOnly(String email, String code, String id) {
        String key = "email"+id+":"+email+":true";
        if (!Objects.isNull(redisCache.getCacheObject(key))){
            String s = (String) redisCache.getCacheObject(key);
            if (null == s) return RestBean.failure("验证码失效，请重新发送");
            if (s.equals(code)){
                redisCache.deleteObject(key);
                return RestBean.success("验证成功");
            }else return RestBean.failure("验证码错误，请检查");
        }else {
            return RestBean.failure("请先获取验证码");
        }
    }

    @Override
    public boolean resetPassword(String password, String email) {
        password = encoder.encode(password);
        return mapper.resetPasswordByEmail(password, email) > 0;
    }
}
